home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 May: Tool Chest / Dev.CD May 98 TC.toast / Tool Chest / Networking / MacTCP / MPing 1.1 / Sources / MPingIcmp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-30  |  12.7 KB  |  437 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2. #    MPing 1.1 - MacTCP Ping Tool
  3. #
  4. #    Copyright © Apple Computer, Inc. 1990-1991
  5. #    All rights reserved.
  6. #
  7. #    Versions:    
  8. #                1.1        September 25, 1991.
  9. #
  10. #    File:
  11. #                MPing.c
  12. #
  13. #    Components:
  14. #                AddressXlation.h
  15. #                MacTCPCommonTypes.h
  16. #                Makefile
  17. #                MiscIPPB.h
  18. #                MPing.c
  19. #                MPing.h
  20. #                MPing.r
  21. #                MPingDlg.c
  22. #                MPingExtern.h
  23. #                MPingGlobals.h
  24. #                MPingIcmp.c
  25. #                MPingWindow.c
  26. #                resolver.c
  27. ------------------------------------------------------------------------------*/
  28.  
  29. #include <values.h>
  30. #include <types.h>
  31. #include <quickdraw.h>
  32. #include <fonts.h>
  33. #include <events.h>
  34. #include <controls.h>
  35. #include <windows.h>
  36. #include <menus.h>
  37. #include <textedit.h>
  38. #include <dialogs.h>
  39. #include <desk.h>
  40. #include <scrap.h>
  41. #include <toolutils.h>
  42. #include <memory.h>
  43. #include <segload.h>
  44. #include <files.h>
  45. #include <osutils.h>
  46. #include <osevents.h>
  47. #include <diskinit.h>
  48. #include <packages.h>
  49. #include <traps.h>
  50. #include <strings.h>
  51. #include <Errors.h>
  52. #include <Devices.h>
  53. #include <String.h>
  54. #include <StdLib.h>
  55. #include <StdIO.h>
  56. #include <AppleTalk.h>
  57.  
  58. #include "MacTCPCommonTypes.h"
  59. #include "MiscIPPB.h"
  60. #include "AddressXlation.h"
  61. #include "MPing.h"
  62. #include "MPingGlobals.h"
  63.  
  64. #ifndef DEBUG
  65. #define DEBUG 1
  66. #endif
  67.  
  68. Boolean waiting = true;
  69. char    gHostAddress[255];            /* Host address */
  70. char    gData[MAX_ICMP_SIZE];        /* ICMP data to be transmitted */
  71. char    gPattern[MAX_ICMP_SIZE];    /* ICMP data pattern to be transmitted */
  72. char    gPatData[MAX_ICMP_SIZE];    /* ICMP data created from the pattern */
  73. char    *gDataPtr;                    /* pointer to the data actually being transmitted */
  74. long    gSize;                        /* size of the ICMP packet */
  75. long    gTempCount=1;                /* used for sending fixed no. of packets */
  76. long    gCount;                        /* no. of ICMP data packets to be transmitted */
  77. long    gWait;                        /* wait no. of ticks before sending each packet */
  78. Boolean    gTextPattern;                /* true to send text, false to send pattern */
  79. Boolean gQuietVerbose;                /* true to quiet, false to verbose */
  80. Boolean gFixedNoOfPkts;                /* true to send fixed no. of packets, false to continue */
  81. struct IPParamBlock gIopbBlk[MAX_IOPB_QUEUE];    /* allocate iopb blocks from this */
  82. struct EchoResponseStatus gResponseStatus;        /* status of echo response */
  83. char    gIPOptionsBlk[MAX_IOPB_QUEUE][MAX_OPT_SIZE];    /* IP options block */
  84. char    gIPOptionResponse[MAX_OPT_SIZE];        /* response from destination host */
  85. short    gIopbIndex;                    /* circular queue, with this index */
  86.  
  87. struct Record_Route_Info gRecord_route;
  88. struct Record_Route_Info gLooseSourceRR;
  89. struct Record_Route_Info gStrictSourceRR;
  90. struct Security_Info gSecurity_Opt;
  91. struct Stream_Indentifier_Info gStream_ID;
  92. struct Internet_Timestamp_Info gInternetTimeStamp;
  93.  
  94. Boolean gRR=false;                    /* flag for Record Route option */
  95. Boolean gLSRR=false;                /* flag for Loose Source Record Route option */
  96. Boolean gSSRR=false;                /* flag for Strict Source Record Route option */
  97. Boolean gSecurity=false;            /* flag for Security option */
  98. Boolean gSID=false;                    /* flag for Stream ID option */
  99. Boolean gTimestamp=false;            /* flag for Internet Timestamp option */
  100.  
  101. Boolean gSessionComplete=false;        /* if false don't send packet, else do */
  102.  
  103. Boolean gResponsePrinted=true;        /* used in verbose option */
  104.  
  105. short    gDrvrRefNum;                /* reference number of .ipp driver */
  106. unsigned long gSourceHostAddress;    /* ip address of the source host */
  107. char gSourceAddress[16];            /* in character format */
  108. unsigned long gDestHostAddress=0;        /* ping to this host address */
  109. char gDestAddress[16];            /* in character format */
  110.  
  111. struct PingStatistics gIcmpStat;    /* used to print icmp ping statistics */
  112.  
  113. void DoIcmpPing(void);
  114. OSErr OpenDriverA(short *refnum);
  115. pascal void appResultProc(struct hostInfo *hostInfoPtr, unsigned longuserDataPtr);
  116. OSErr IcmpPingSetup(void);
  117. void FillOurPattern(void);
  118. void SendIcmpEcho(void);
  119. void TestCompletion(struct ICMPParamBlock *iopb);
  120. short FillInIPOptionBlk(char * IPOptionsBlk);
  121. extern void bzero(char *ptr, int cnt);
  122. void mycopy(char *dest, char *src, short noOfBytes);
  123. extern void WarnUser(short error);
  124. void IsHostAlive(void);
  125. void TestCompletion1(struct ICMPParamBlock *iopb);
  126.  
  127.  
  128. void SendIcmpEcho(void)
  129. {
  130.     OSErr err;
  131.     short qStart, qEnd;                                /* indices for circular queue */
  132.     short optionLength;
  133.  
  134.     if ((gFixedNoOfPkts == false) || (gTempCount)) {    /* send fixed no. of packets, check the count */
  135.         qStart = gIopbIndex;    /* find the first free block */
  136.         qEnd = (gIopbIndex ? gIopbIndex-1 : MAX_IOPB_QUEUE-1);
  137.         
  138.         while ( (gIopbBlk[qStart].ioResult == 1) && (qStart != qEnd) ) {
  139.             qStart++;
  140.             if (qStart == MAX_IOPB_QUEUE)
  141.                 qStart = 0;
  142.         }
  143.         gIopbIndex = qStart;
  144.         if (gIopbBlk[gIopbIndex].ioResult < 1) {
  145.             gIcmpStat.totPktOut++;
  146.             gIopbIndex = qStart;
  147.             bzero((char *)&(gIopbBlk[gIopbIndex]), sizeof(struct IPParamBlock));
  148.             gIopbBlk[gIopbIndex].ioCRefNum = gDrvrRefNum;
  149.             gIopbBlk[gIopbIndex].csCode = ipctlEchoICMP;
  150.             gIopbBlk[gIopbIndex].csParam.IPEchoPB.dest = gDestHostAddress;
  151.             gIopbBlk[gIopbIndex].csParam.IPEchoPB.data.ptr = gDataPtr;
  152.             gIopbBlk[gIopbIndex].csParam.IPEchoPB.data.length = gSize;
  153.             gIopbBlk[gIopbIndex].csParam.IPEchoPB.timeout = 1;
  154.             optionLength = FillInIPOptionBlk(gIPOptionsBlk[gIopbIndex]);
  155.             if (optionLength > MAX_OPT_SIZE) {
  156.                 gIopbBlk[gIopbIndex].csParam.IPEchoPB.options = (Ptr) nil;
  157.                 gIopbBlk[gIopbIndex].csParam.IPEchoPB.optLength = 0;
  158.             }
  159.             else {
  160.                 gIopbBlk[gIopbIndex].csParam.IPEchoPB.options = (Ptr) gIPOptionsBlk[gIopbIndex];
  161.                 gIopbBlk[gIopbIndex].csParam.IPEchoPB.optLength = optionLength;
  162.             }
  163.             gIopbBlk[gIopbIndex].csParam.IPEchoPB.icmpCompletion = (ICMPEchoNotifyProc) TestCompletion;
  164.             gIopbBlk[gIopbIndex].csParam.IPEchoPB.userDataPtr = gIcmpStat.totPktOut;
  165.             err = PBControl((ParamBlockRec *)&(gIopbBlk[gIopbIndex]), true);
  166.         }
  167.         gIopbIndex++;            /* mark next queue element as current */
  168.         if (gIopbIndex == MAX_IOPB_QUEUE)    gIopbIndex = 0;
  169.     }
  170.     if ((gFixedNoOfPkts == true) && (gTempCount <= 0))    /* we are done */
  171.         gSessionComplete = true;
  172.                     /* see if we are not getting any responses after sending many echoes */
  173.     if ((gIcmpStat.totPktOut >= MAX_PKT_NO_RESP) && (gIcmpStat.totPktIn == 0))
  174.         gSessionComplete = true;
  175. }
  176.  
  177. void TestCompletion(iopb)
  178. struct ICMPParamBlock *iopb;
  179. {
  180.     unsigned long thisTime;
  181.  
  182.     if (gQuietVerbose == true)
  183.         gResponsePrinted = true;
  184.     else gResponsePrinted = false;
  185.     thisTime = iopb->icmpEchoInfo.echoReplyIn - iopb->icmpEchoInfo.echoRequestOut;
  186.     gResponseStatus.rt_time = thisTime;
  187.     gResponseStatus.pkt_len = iopb->icmpEchoInfo.echoedData.length - 8;
  188.     gResponseStatus.pkt_no = iopb->icmpEchoInfo.userDataPtr;
  189.  
  190.     if (iopb->ioResult == noErr) {
  191.         gResponseStatus.response_ok = true;
  192.         if (iopb->icmpEchoInfo.options != nil)
  193.             mycopy(gIPOptionResponse, iopb->icmpEchoInfo.options, sizeof(struct Record_Route_Info));
  194.  
  195.         gIcmpStat.totPktIn++;                    /* update ICMP ping statistics */
  196.         gIcmpStat.totTime += thisTime;
  197.         if (iopb->icmpEchoInfo.userDataPtr == 1) {    /* first packet */
  198.             gIcmpStat.minTime = thisTime;
  199.             gIcmpStat.maxTime = thisTime;
  200.         }
  201.         else {
  202.             if (thisTime < gIcmpStat.minTime)
  203.                 gIcmpStat.minTime = thisTime;        /* update min round-trip time */
  204.             else
  205.                 if (thisTime > gIcmpStat.maxTime)
  206.                     gIcmpStat.maxTime = thisTime;    /* update max round-trip time */
  207.         }
  208.         if ((gFixedNoOfPkts == true) && (gTempCount > 0))
  209.             gTempCount--;                        /* we are not considering duplicate replies */
  210.      }
  211.     else {
  212.         gIcmpStat.totPktBad++;
  213.         gResponseStatus.response_ok = false;
  214.     }
  215. }
  216.  
  217. OSErr IcmpPingSetup(void)
  218. {
  219.     OSErr err;
  220.     struct hostInfo hostInfo;
  221.     unsigned long userDataPtr = 0X123456789;
  222.     short refNum;
  223.     char driverName[] = {'\4', '.', 'i', 'p', 'p'};
  224.  
  225.     gIcmpStat.minTime = 0;
  226.     gIcmpStat.avgTime = 0;
  227.     gIcmpStat.maxTime = 0;
  228.     gIcmpStat.totTime = 0;
  229.     gIcmpStat.totPktOut = 0;
  230.     gIcmpStat.totPktIn = 0;
  231.     gIcmpStat.totPktBad = 0;
  232.  
  233.     gResponseStatus.pkt_no = 0;
  234.     gResponseStatus.rt_time = 0;
  235.     gResponseStatus.pkt_len = 0;
  236.     gResponseStatus.response_ok = true;
  237.  
  238.     err = OpenDriverA(&refNum);
  239.     if (err == noErr) {
  240.         gDrvrRefNum = refNum;
  241.         err =  StrToAddr(gHostAddress, &hostInfo, (ResultProcPtr) appResultProc, (char *)userDataPtr);
  242.         if (hostInfo.rtnCode == cacheFault) {
  243.             while (waiting == true) {};
  244.             waiting = true;
  245.         }
  246.         gDestHostAddress = hostInfo.addr[0];
  247.         (void) AddrToStr(gDestHostAddress, gDestAddress);
  248.         err = hostInfo.rtnCode;
  249.     }
  250.  
  251.     bzero((char *) &(gIopbBlk[0]), sizeof(struct IPParamBlock) * MAX_IOPB_QUEUE);
  252.     bzero(gIPOptionResponse, MAX_OPT_SIZE); 
  253.     if (err == noErr) {                /* set up the global environment */
  254.         if (gCount < 0) gCount = DEFAULT_PKT_COUNT;
  255.         if (gSize <= 0) gSize = DEFAULT_ICMP_SIZE;
  256.         else
  257.             if (gSize > MAX_ICMP_SIZE) gSize = MAX_ICMP_SIZE;
  258.         if (gWait < MIN_TIME_DELAY) gWait = MIN_TIME_DELAY;
  259.         if (gFixedNoOfPkts == true) gTempCount = gCount;
  260.         if (gTextPattern == true) {    /* fill the packet with the data */
  261.             gDataPtr = &gData;
  262.         }
  263.         else {                        /* fill the packet with the pattern */
  264.             FillOurPattern();
  265.             gDataPtr = &gPatData;
  266.         }
  267.         gIopbIndex = 0;
  268.     }
  269.     return(err);
  270. }
  271.  
  272. OSErr OpenDriverA(refnum)
  273. short *refnum;
  274. {
  275.     IOParam iopb;
  276.     struct IPParamBlock1 tiopb;
  277.     OSErr err;
  278.     static char driverName[] = {'\4', '.', 'i', 'p', 'p'};
  279.  
  280.     bzero((char *)&iopb, sizeof(iopb));
  281.     iopb.ioNamePtr = &driverName;
  282.     iopb.ioPermssn = fsCurPerm;
  283.  
  284.     err = PBOpen((ParamBlockRec *)&iopb, false);
  285.     if (err != noErr) {
  286.         return(err);
  287.     }
  288.     else {
  289.         *refnum = iopb.ioRefNum;
  290.         bzero((char *)&tiopb, sizeof(tiopb));
  291.         tiopb.ioCRefNum = *refnum;
  292.         tiopb.csCode = ipctlGetAddr;
  293.         err = PBControl((ParamBlockRec *) &tiopb, false);
  294.         if (err == noErr) {
  295.             gSourceHostAddress = tiopb.ourAddress;
  296.             (void) AddrToStr(gSourceHostAddress, gSourceAddress);
  297.         }
  298.         else gSourceHostAddress = 0;
  299.     }
  300.     return(err);
  301. }
  302.  
  303. pascal void appResultProc(hostInfoPtr, userDataPtr)
  304. struct hostInfo *hostInfoPtr;
  305. #pragma unsigned long userDataPtr;
  306. {
  307.     waiting = false;
  308. }
  309.  
  310. void FillOurPattern(void)
  311. {
  312.     short i, j, k, index=0, len;
  313.     char tHighByte[] = {0x0F,0x1F,0x2F,0x3F,0x4F,0x5F,0x6F,0x7F,0x8F,0x9F,
  314.                         0xAF,0xBF,0xCF,0xDF,0xEF,0xFF};
  315.     char tLowByte[] = {0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,
  316.                         0xFA,0xFB,0xFC,0xFD,0xFE,0xFF};
  317.  
  318.     len = strlen(gPattern);
  319.     for (i=0; (i<len) && (index!=-1); i++) {
  320.         if ((gPattern[i] >= '0') && (gPattern[i] <= '9'))
  321.             index = gPattern[i] - '0';
  322.         else
  323.             if ((gPattern[i] >= 'A') && (gPattern[i] <= 'F'))
  324.                 index = gPattern[i] - 'A' + 10;
  325.             else
  326.                 if ((gPattern[i] >= 'a') && (gPattern[i] <= 'f'))
  327.                     index = gPattern[i] - 'a' + 10;
  328.                 else index = -1;
  329.         if (index != -1) {
  330.             for (j=i; j<2*gSize; j+=len) {
  331.                 k = j / 2;
  332.                 if (!(j % 2)) {
  333.                     gPatData[k] |= MASK_HIGH;
  334.                     gPatData[k] &= tHighByte[index];
  335.                 }
  336.                 else {
  337.                     gPatData[k] |= MASK_LOW;
  338.                     gPatData[k] &= tLowByte[index];
  339.                 }
  340.             }
  341.         }
  342.     }
  343. }
  344.  
  345. short FillInIPOptionBlk(IPOptionsBlk)
  346. char *IPOptionsBlk;
  347. {
  348.     Boolean optionsPresent=false;
  349.     short    index1=0;
  350.  
  351.     bzero(IPOptionsBlk, MAX_OPT_SIZE);
  352.  
  353.     if (gRR) {
  354.         bzero((char *)&gRecord_route, 23);
  355.         gRecord_route.opt_type = IPO_RR;
  356.         gRecord_route.opt_len = 23;
  357.         gRecord_route.opt_ptr = 4;
  358.  
  359.         mycopy(IPOptionsBlk, (char *) &gRecord_route, 23);
  360.         index1 += 23;
  361.         optionsPresent = true;
  362.     }
  363.     if (gLSRR) {
  364.         bzero((char *)&gLooseSourceRR, 23);
  365.         gLooseSourceRR.opt_type = IPO_LSRR;
  366.         gLooseSourceRR.opt_len = 23;
  367.         gLooseSourceRR.opt_ptr = 4;
  368.  
  369.         mycopy((char *) &IPOptionsBlk[index1], (char *) &gLooseSourceRR, 23);
  370.         index1 += 23;
  371.         optionsPresent = true;
  372.     }
  373.     if (gSSRR) {
  374.         bzero((char *)&gStrictSourceRR, 23);
  375.         gStrictSourceRR.opt_type = IPO_SSRR;
  376.         gStrictSourceRR.opt_len = 23;
  377.         gStrictSourceRR.opt_ptr = 4;
  378.  
  379.         mycopy((char *) &IPOptionsBlk[index1], (char *) &gStrictSourceRR, 23);
  380.         index1 += 23;
  381.         optionsPresent = true;
  382.     }
  383.     if (gSecurity) {
  384.         bzero((char *)&gSecurity_Opt, 11);
  385.         gSecurity_Opt.opt_type = IPO_SEC;
  386.         gSecurity_Opt.opt_len = 11;
  387.  
  388.         mycopy((char *) &IPOptionsBlk[index1], (char *) &gSecurity_Opt, 11);
  389.         index1 += 11;
  390.         optionsPresent = true;
  391.     }
  392.     if (gSID) {
  393.         bzero((char *)&gStream_ID, 4);
  394.         gStream_ID.opt_type = IPO_SID;
  395.         gStream_ID.opt_len = 4;
  396.  
  397.         mycopy((char *) &IPOptionsBlk[index1], (char *) &gStream_ID, 4);
  398.         index1 += 4;
  399.         optionsPresent = true;
  400.     }
  401.     if (gTimestamp) {
  402.         bzero((char *)&gInternetTimeStamp, 36);
  403.         gInternetTimeStamp.opt_type = IPO_TIME;
  404.         gInternetTimeStamp.opt_len = 36;
  405.         gInternetTimeStamp.opt_ptr = 5;
  406.  
  407.         mycopy((char *) &IPOptionsBlk[index1], (char *) &gInternetTimeStamp, 36);
  408.         index1 += 36;
  409.         optionsPresent = true;
  410.     }
  411.     if (optionsPresent) {
  412.             /* The size of the option block should be of multiple of 4 */
  413.             /* 4 bytes = 32 bits => (bingo !) offset boundary */
  414.         while ((index1 + 1)  % 4)                /* stuff the required space by */
  415.             IPOptionsBlk[index1++] = IPO_NOP;    /* no operation (noop) option code */
  416.         IPOptionsBlk[index1] = IPO_EOL;
  417.         index1++;
  418.     }
  419.     return(index1);
  420. }
  421.  
  422. void bzero(ptr, cnt)
  423. char *ptr;
  424. int cnt;
  425. {
  426.     while (cnt--) *ptr++ = 0;
  427. }
  428.  
  429. void mycopy(dest, src, noOfBytes)
  430. char *dest;
  431. char *src;
  432. short noOfBytes;
  433. {
  434.     while (noOfBytes--)
  435.         *dest++ = *src++;
  436. }
  437.